using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

using log4net;

namespace FreeBase.Linq
{
	/// <summary>
	/// Description of QueryProvider.
	/// </summary>
	public abstract class QueryProvider : IQueryProvider
	{
private readonly ILog logger = LogManager.GetLogger( typeof( ResponseParser ) );
		
		IQueryable IQueryProvider.CreateQuery(Expression expression)
		{
			Type elementType = TypeSystem.GetElementType(expression.Type);
			try
			{
				return (IQueryable)Activator.CreateInstance(typeof(Query<>).MakeGenericType(elementType), new object[] { this, expression });
			}
			catch (TargetInvocationException tie)
			{
				throw tie.InnerException;
			}
		}

		public object Execute(Expression expression)
		{
			return this.Execute<object>(expression);
		}

		public abstract string GetQueryText(Expression expression);
		public abstract TResult Execute2<TResult>(Expression expression);
		
		IQueryable<TElement> IQueryProvider.CreateQuery<TElement>(Expression expression)
		{
			logger.Debug( "Running QueryProvider.CreateQuery<TElement> method" );
			return new Query<TElement>(this, expression);
		}
		
		/// <summary>
		/// 
		/// </summary>
		/// <remarks>
		/// Implements IQueryProvider.Execute( Expression )
		/// </remarks>
		/// <param name="expression"></param>
		/// <returns></returns>
		public TResult Execute<TResult>( Expression expression )
		{
			logger.Debug( "Running QueryProvider.Execute<TResult> method with TResult a type of " + typeof(TResult).Name );
			return (TResult)this.Execute2<TResult>(expression);
		}
	}
}
